package net.stogi.dsper.back.service.impl;

import java.util.ArrayList;
import java.util.List;

import net.stogi.common.api.dto.OrderBy;
import net.stogi.common.api.exception.BusinessException;
import net.stogi.dsper.api.dto.DataSourceDto;
import net.stogi.dsper.api.model.DataSource;
import net.stogi.dsper.api.model.User;
import net.stogi.dsper.api.service.DataSourceService;
import net.stogi.dsper.api.util.ModelToDtoConverterUtils;
import net.stogi.dsper.back.dao.DataSourceDao;
import net.stogi.dsper.back.service.DataSourceInternalService;
import net.stogi.dsper.back.service.UserInternalService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("DsperBack.Service.DataSourceService")
public class DataSourceServiceImpl implements DataSourceService, DataSourceInternalService {

	private static final Logger log = LoggerFactory.getLogger(DataSourceServiceImpl.class);

	@Autowired
	private DataSourceDao dataSourceDao;

	@Autowired
	private UserInternalService userService;

	@Override
	public DataSource getDataSourceWithChecks(Long id) throws BusinessException {
		assert id != null : "Parameter 'id' can not be null";

		// Load data source.
		DataSource dataSource = dataSourceDao.loadById(id, false);

		// Check data source.
		if (dataSource == null) {
			log.warn("Data source with given id does not exist: [dataSourceId = '{}']", id);
			throw new BusinessException("Data source with given id does not exist: [dataSourceId = '" + id + "']");
		}

		return dataSource;
	}

	@Override
	@Transactional(rollbackFor = BusinessException.class)
	public List<DataSourceDto> listDataSources(Long userId) throws BusinessException {
		log.trace("listDataSources(): invoke: [userId = '{}']", userId);

		List<DataSourceDto> dataSourceDtoList = new ArrayList<DataSourceDto>();

		User user = userService.getUserWithChecks(userId);

		List<DataSource> dataSourceList = dataSourceDao.loadByUser(user, OrderBy.asc("name"));

		for (DataSource dataSource : dataSourceList) {
			dataSourceDtoList.add(ModelToDtoConverterUtils.convertDataSourceModelToDto(dataSource));
		}

		return dataSourceDtoList;
	}

	@Override
	@Transactional(rollbackFor = BusinessException.class)
	public Long saveDataSource(Long userId, DataSourceDto dataSourceDto) throws BusinessException {
		log.trace("saveDataSource(): invoke: [userId = '{}', dataSourceDto = '{}']", userId, dataSourceDto);
		assert userId != null : "Parameter 'userId' can not be null";
		assert dataSourceDto != null : "Parameter 'dataSourceDto' can not be null";

		// Load user.
		User user = userService.getUserWithChecks(userId);

		DataSource dataSource = null;
		// Update data source.
		if (dataSourceDto.getId() != null) {
			dataSource = dataSourceDao.loadById(dataSourceDto.getId(), true);
		}
		// Create new data source.
		else {
			dataSource = new DataSource();
			dataSource.setUser(user);
		}

		updateDataSourceModelAgainstDto(dataSource, dataSourceDto);

		dataSourceDao.save(dataSource);

		return dataSource.getId();
	}

	private void updateDataSourceModelAgainstDto(DataSource model, DataSourceDto dto) {
		BeanUtils.copyProperties(dto, model, new String[] { "id" });
	}
}
